package com.dragon.blelibrary.events;


import com.dragon.blelibrary.BleConfig;

import java.util.ArrayList;
import java.util.Iterator;

/*
 * 消息推送工具类
 * 具备：一对多，一对一，模式
 */
public class BlePropertyObservable {

    /* 添加观察模式的集合**/
    private MultiHashMap<BleEventImp, BleEvent> map = new MultiHashMap<>();
    private static BlePropertyObservable instance;

    /**
     * 对外，统一提供单例
     *
     * @return
     */
    public synchronized static BlePropertyObservable getInstance() {
        if (instance == null) {
            instance = new BlePropertyObservable();
        }
        return instance;
    }

    private BlePropertyObservable() {

    }

    /**
     * 或取对eventId这个消息监听的数目
     *
     * @param eventId
     * @return
     */
    public int getListenerCount(BleEventImp eventId) {
        ArrayList<BleEvent> ls = map.get(eventId);
        if (null != ls) {
            return ls.size();
        }
        return 0;
    }

    /**
     * 是否有对eventId这个消息的监听
     *
     * @param eventId
     * @return
     */
    public boolean hasListener(BleEventImp eventId) {
        return getListenerCount(eventId) > 0;
    }

    public int size() {
        return map.size();
    }
    /**
     * 注册单个监听器
     * @param listener
     * @param eventIds
     */
//	public synchronized void setListener(ObservableID eventId, BleEvent listener) {
//		if(null==listener) return;
//		map.remove(eventId);
//		map.put(eventId, listener);
//	}

    /**
     * 注册多个监听器
     *
     * @param listener
     * @param eventIds
     */
    public synchronized void addListener(BleEvent listener, BleEventImp eventIds[]) {
        if (null == listener || null == eventIds) return;
        for (BleEventImp id : eventIds) {
            map.put(id, listener);
        }
    }

    /**
     * 注册单个监听器
     *
     * @param listener
     * @param eventIds
     */
    public synchronized void addListener(BleEvent listener, BleEventImp eventIds) {
        if (null == listener) return;
        map.put(eventIds, listener);
    }

    /**
     * 移除多个
     *
     * @param listener
     * @param eventIds
     */
    public synchronized void removeListener(BleEvent listener, BleEventImp... eventIds) {
        if (null == listener || null == eventIds) return;
        for (BleEventImp id : eventIds) {
            map.remove(id, listener);
        }
    }

    /**
     * 移除某个地的监听器
     * @param eventIds
     */
    public synchronized void removeEvents(BleEventImp... eventIds){
        if(null == eventIds)
            return;
        for (BleEventImp id : eventIds) {
            map.remove(id);
        }
    }

    /**
     * 移除相同eventI'd的class，效率低
     * @param listener
     * @param eventIds
     */
    public synchronized void removeListenerClass(BleEvent listener,BleEventImp... eventIds){
        if(null == listener || eventIds == null)
            return;
        for (BleEventImp id : eventIds) {
            ArrayList<BleEvent> events = map.get(id);
            if(events != null && !events.isEmpty()){
                Iterator<BleEvent> it = events.iterator();
                while(it.hasNext()){
                    BleEvent e = it.next();
                    if(e != null && e.getClass().getName().equals(listener.getClass().getName())){
                        it.remove();
                    }
                }
            }
        }
    }
    /**
     * 低效率, 需要遍历
     *
     * @param listener
     */
    public synchronized void removeListener(BleEvent listener) {
        if (null == listener) return;
        map.removeValue(listener);
    }

    public synchronized void clearListeners() {
        map.clear();
    }

    /**
     * 本方法可在子线程或主线程调用，但是最终结果回调为主线程
     *
     * @param eventId 事件id
     * @param address 返回结果实体类
     * @param args    其他类型的结果
     */
    public void fireEvent(final BleEventImp eventId, final String address, final Object... args) {
        int size = 0;
        BleEvent[] arrays = null;
        synchronized (this) {
            ArrayList<BleEvent> ls = map.get(eventId);
            if (null == ls) {
                return;
            }
            size = ls.size();
            arrays = new BleEvent[size];
            ls.toArray(arrays);
        }
        if (null != arrays) {
            for (int i = arrays.length - 1; i >= 0; i--) {
                final BleEvent observer = arrays[i];
//			}
//			for (final BleEvent observer : arrays) {
                if (null != observer) {
//                    Log.i("event",observer.getClass().getName() + "-->" + eventId);
                    try {
                        BleConfig.mHandler.post(new Runnable() {

                            @Override
                            public void run() {
                                observer.updateView(eventId, address, args);
                            }
                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
    /**
     * 同步调用
     *
     * @param eventId 事件id
     * @param address 返回结果实体类
     * @param args    其他类型的结果
     */
    public void fireEventSync(final BleEventImp eventId, final String address, final Object... args) {
        int size = 0;
        BleEvent[] arrays = null;
        synchronized (this) {
            ArrayList<BleEvent> ls = map.get(eventId);
            if (null == ls) {
                return;
            }
            size = ls.size();
            arrays = new BleEvent[size];
            ls.toArray(arrays);
        }
        if (null != arrays) {
            for (int i = arrays.length - 1; i >= 0; i--) {
                final BleEvent observer = arrays[i];
//			}
//			for (final BleEvent observer : arrays) {
                if (null != observer) {
//                    Log.i("event",observer.getClass().getName() + "-->" + eventId);
                    try {
//                        BleConfig.mHandler.post(new Runnable() {
//
//                            @Override
//                            public void run() {
                                observer.updateView(eventId, address, args);
//                            }
//                        });
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
